#include "SceneMgr.h"
#include "MapMgr.h"
#include "Character/monster/MonsterRefCfg.h"
#include "Character/monster/MonsterRefMgr.h"
#include "Common/Utility/ServerTime.h"
#include "Character/PlayerMgr.h"
#include "Common/SceneDefine.h"
#include "Character/monster/Monster.h"
#include "Character/npc/Npc.h"
#include "Character/drop/Drop.h"

#include "Character/object/Object.h"
#include "Rebot/Rebot.h"

#include  <list>
SceneMgr::SceneMgr()
{
	m_Scenes.clear();
	m_countId = 0;
}

SceneMgr::~SceneMgr()
{
}

bool SceneMgr::Init()
{
	//例如第一层m_mapLyaer[1]
	//  00000
	//	01110
	//	01010
	//	01110
	//	00000
	//******************计算每层所需定位的格子******************
	m_mapLayer[0].push_back({ 0, 0 });
	for (int a = 1; a <= MAX_LAYER; a++)
	{
		/*
		for (int x = -a; x <= a; x++)
		{
			for (int y = -a; y <= a; y++)
			{
				if ((abs(x) < a - 1 && abs(y) < a - 1) || (x == 0 && y == 0))
					continue;
				m_mapLayer[a].push_back({ x, y });
			}
		}
		*/

		{
			int y = -a;
			for (int x = -a; x <= a; x++)
			{
				m_mapLayer[a].push_back({ x, y });
			}
		}

		{
			int y = a;
			for (int x = -a; x <= a; x++)
			{
				m_mapLayer[a].push_back({ x, y });
			}
		}

		{
			int x = -a;
			for (int y = -a + 1; y <= a - 1; y++)
			{
				m_mapLayer[a].push_back({ x, y });
			}
		}

		{
			int x = a;
			for (int y = -a + 1; y <= a - 1; y++)
			{
				m_mapLayer[a].push_back({ x, y });
			}
		}
	}

	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
		return false;
	//处理重定向，广播等
	pMessageDispatch->registerServerHandler(EMODULE_ID_SCENE, this);

	return true;
}

bool SceneMgr::UnInit()
{
	mapScenes::iterator iter = m_Scenes.begin();
	uint32_t mapId = 0;
	Scene* pScene = nullptr;
	for (; iter != m_Scenes.end(); iter++)
	{
		pScene = iter->second;
		if (!pScene || !pScene->UnInit())
		{
			LogErrFmtPrint("scene unit error, sceneId:%d", iter->first);
			continue;
		}
		mapId = iter->second->GetMapId();
		m_mapSceneObjPool[mapId]->FreeObj(iter->second);
		iter->second = nullptr;
	}

	mapObjPool::iterator poolIter = m_mapSceneObjPool.begin();
	for (; poolIter != m_mapSceneObjPool.end(); poolIter++)
	{
		delete poolIter->second;
		poolIter->second = nullptr;
	}
	m_mapSceneObjPool.clear();
	m_delCacheMap.clear();
	m_Scenes.clear();
	return true;
}

bool SceneMgr::InitRunSceneUseMapConfig(CONFIGMAPIDLST& list)
{
	std::unordered_map<uint32_t, Map*> *pMaps = g_GetMapMgr()->GetAllMaps();
	if (nullptr == pMaps)
	{
		LogErrFmtPrint("logic srv mapid list is empty, and config maps size==0 logicId:%d", g_GetLogicService()->GetID());
		return false;
	}

	auto iter = pMaps->begin();
	auto iterEnd = pMaps->end();
	for (; iter != iterEnd; iter++)
	{
		ObjectPool<Scene> *pScenePool = nullptr;
		Map *pMap = nullptr;
		pMap = iter->second;
		if (!pMap)
		{
			LogErrFmtPrint("create static map err, getmap null, mapId:%d", iter->first);
			continue;
		}
		pScenePool = new ObjectPool<Scene>(1, false);
		if (nullptr == pScenePool)
		{
			LogErrFmtPrint("[logic] SceneMgr::InitRunSceneUseMapConfig.....nullptr == pScenePool....mapid:%u ", iter->first);
			return false;
		}
		m_mapSceneObjPool[pMap->GetId()] = pScenePool;
		//启动服务器时创建 非动态场景
		if (!pMap->IsDynamic())
		{
			CreateScene(pMap->GetId(), pMap->GetId());
		}
		list.push_back(iter->first);
	}
	return true;
}

bool SceneMgr::InitRunSceneInLogic(CONFIGMAPIDLST& list)
{
	auto iter = list.begin();
	auto iterEnd = list.end();
	for (; iter != iterEnd; iter++)
	{
		ObjectPool<Scene> *pScenePool = nullptr;
		Map *pMap = nullptr;
		pMap = g_GetMapMgr()->GetMap(*iter);
		if (!pMap)
		{
			LogErrFmtPrint("[logic] create static map err, getmap null, mapId:%u", *iter);
			continue;
		}
		pScenePool = new ObjectPool<Scene>(1, false);
		if (nullptr == pScenePool)
		{
			LogErrFmtPrint("[logic] SceneMgr::InitRunSceneInLogic.....nullptr == pScenePool....mapid:%u ", *iter);
			return false;
		}
		m_mapSceneObjPool[pMap->GetId()] = pScenePool;
		//启动服务器时创建 非动态场景
		if (!pMap->IsDynamic()) 
		{
			CreateScene(pMap->GetId(), pMap->GetId());
		}
	}
	return true;
}

Scene* SceneMgr::GetScene(uint32_t sceneId)
{
	mapScenes::iterator iter = m_Scenes.find(sceneId);
	if (iter == m_Scenes.end())
		return NULL;
	return  iter->second;
}

bool SceneMgr::CreateSceneReq(const char *data, uint32_t len)
{
	bool result = false;
	bool retCode = false;
	uint32_t sceneId = 0;
	uint32_t mapId = 0;
	LogDebugFmtPrint("CreateSceneFromCenter, len:%d", len);
	CenterCreateSceneReq createreq;

	{
		retCode = createreq.ParseFromArray(data, len);
		MMOLOG_PROCESS_ERROR(retCode);
		sceneId = createreq.sceneid();
		mapId = createreq.mapid();
		retCode = (nullptr != CreateScene(mapId, sceneId));
		MMOLOG_PROCESS_ERROR(retCode);

		CenterCreateSceneRsp creatersp;
		creatersp.set_sceneid(sceneId);
		creatersp.set_mapid(mapId);
		retCode = g_GetLogicService()->SendDataToCenter(EMODULE_ID_SCENE, CENTER_CREATE_SCENE_RSP_LOGIC, &creatersp);
		MMOLOG_PROCESS_ERROR(retCode);

		result = true;
	}

	result = true;
Exit0:
	if (createreq.has_param())
	{
		CreateSceneParamProto *pparam = createreq.mutable_param();
		if (nullptr != pparam)
		{
			int8_t param_type = pparam->param_type();
			string strParam = pparam->SerializeAsString();
			// nSrcID : 场景ID,
			g_GetEvent()->FireExecute(EVENT_CREATE_SCENE, sceneId, param_type, (void*)strParam.c_str(), strParam.length());
		}
	}

	return result;
}

Scene* SceneMgr::CreateScene(uint32_t mapId, uint32_t sceneId)
{
	uint32_t sid = g_GetLogicService()->GetID();
	Map *pMap = g_GetMapMgr()->GetMap(mapId);
	if (nullptr == pMap)
	{
		LogErrFmtPrint("[logic] SceneMgr::CreateScene nullptr == pMap ,sid:%u, mapId:%u sceneId:%u",sid, mapId, sceneId);
		return nullptr;
	}
	if (GetScene(sceneId))
	{
		LogErrFmtPrint("[logic] SceneMgr::CreateScene scene already exists ,sid:%u,  mapId:%u sceneId:%u", sid,mapId, sceneId);
		return nullptr;
	}

	Scene *pScene = nullptr;
	pScene = m_mapSceneObjPool[mapId]->MallocObj();
	if (nullptr == pScene)
	{
		LogErrFmtPrint("[logic] SceneMgr::CreateScene  malloc new scene obj failed.. ,sid:%u,  mapId:%u sceneId:%u", sid,mapId, sceneId);
		return nullptr;
	}
	if (!pScene->Init(mapId, sceneId))
	{
		m_mapSceneObjPool[mapId]->FreeObj(pScene);
		LogErrFmtPrint("[logic] SceneMgr::CreateScene  scene init failed.. ,sid:%u,  mapId:%u sceneId:%u", sid,mapId, sceneId);
		return nullptr;
	}
		
	m_Scenes[sceneId] = pScene;
	g_GetGeneralCreatureRefMgr()->InitSceneRef(mapId, sceneId);
	LogDebugFmtPrint("[logic] SceneMgr::CreateScene success...  sid:%u,  sceneid:%u--mapid:%u", sid, sceneId, pScene->GetMapId());
	return pScene;
}

bool SceneMgr::RecyclScene(uint32_t sceneId)
{
	mapScenes::iterator iter = m_Scenes.find(sceneId);
	if (iter == m_Scenes.end())
		return false;
	Scene *pScene = iter->second;
	m_Scenes.erase(iter);

	if (!pScene || !pScene->UnInit())
	{
		LogErrFmtPrint("[logic] SceneMgr::RecyclScene....!pScene || !pScene->UnInit()...sceneid:%u ", sceneId);
		return false;
	}

	m_mapSceneObjPool[pScene->GetMapId()]->FreeObj(pScene);
	pScene = nullptr;
	return true;
}

bool SceneMgr::DestoryScene(uint32_t scecenId)
{
	Scene *pScene = GetScene(scecenId);
	if (!pScene || !pScene->IsDynamic())
		return false;
	m_delCacheMap[scecenId] = g_GetGlobalServerTime()->Tick();

	LogDebugFmtPrint("[loigic] DestoryScene....logicid:%u, sceneid:%u, mapid:%u ", g_GetLogicService()->GetID(),scecenId,pScene->GetMapId());
	NotifyLogicSceneClose nsdCenter;
	nsdCenter.set_sceneid(scecenId);
	nsdCenter.set_mapid(pScene->GetMapId());
	if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_SCENE, LOGIC_NOTIFY_DESTORY_SCENE_CENTER, &nsdCenter))
	{
		LogErrFmtPrint("[logic] SceneMgr::DestoryScene.....SendDataToCenter failed...id:%u, sceneid:%u, mapid:%u ",g_GetLogicService()->GetID(),scecenId,pScene->GetMapId());
	}

	return true;
}

bool SceneMgr::Update(uint64_t tick)
{
	Scene *pScene = nullptr;
	mapScenes::iterator iter = m_Scenes.begin();
	for (; iter != m_Scenes.end(); iter++)
	{
		pScene = iter->second;
		if (pScene)
			pScene->Update(tick);
	}

	//int64_t curTick = g_GetGlobalServerTime()->Tick();
	DELMAP::iterator Diter = m_delCacheMap.begin();
	while (Diter != m_delCacheMap.end())
	{
		if (tick - Diter->second > 30000)
		{
			if (RecyclScene(Diter->first))
			{
				Diter = m_delCacheMap.erase(Diter);
				continue;
			}
		}
		++Diter;
	}

	return true;
}

const vecPoint2* SceneMgr::GetLayerPoint(uint32_t nlayer)
{
	if (nlayer > MAX_LAYER)
		nlayer = MAX_LAYER;
	return &m_mapLayer[nlayer];
}
void SceneMgr::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (package.cmd)
	{
	case CENTER_CREATE_SCENE_REQ_LOGIC:
		CreateSceneReq(package.dataAfterHead, package.sizeAfterHead);
		break;
	case CENTER_CREATURE_TRANS_SCENE_RSP_LOGIC_RESULT:
		CreatureTransSceneResult(package.dataAfterHead, package.sizeAfterHead);
		break;
	case CENTER_CREATURE_TRANS_SCENE_RSP_LOGIC_SUCCESS:
		CreatureTransSceneSuccess(package.dataAfterHead, package.sizeAfterHead);
		break;
	default:
		LogErrFmtPrint("sceneMgr onServerMessag from center, cmd not rsphandle cmd:%d, len:%d ", package.cmd, package.len);
		break;
	}
}

//生物切换场景成功
bool SceneMgr::CreatureTransSceneSuccess(const char *data, uint32_t len)
{
	uint32_t id = g_GetLogicService()->GetID();
	CenterCreatureTransSceneSuccessRsp successRsp;
	if (!successRsp.ParseFromArray(data, len))
	{
		LogErrFmtPrint("[logic] SceneMgr::CreatureTransSceneSuccess....CenterCreatureTransSceneSuccessRsp parse failed...id:%u ", id);
		return false;
	}
	uint32_t dstSceneId = successRsp.dst_sceneid();
	uint32_t dstMapId = successRsp.dst_mapid();
	const CreatureTransParam &trans_param = successRsp.param();
	int32_t creature_kind = trans_param.creature_kind();
	CharIDType creature_cid = trans_param.creature_cid();

	LogDebugFmtPrint("[logic] SceneMgr::CreatureTransSceneSuccess...id:%u , dstscene:%u, dstmap:%u ,cid:%llu, kind:%d ", id,dstSceneId,dstMapId,creature_cid,creature_kind);
	//判断目标场景是否存在
	Scene* pScene = GetScene(dstSceneId);
	if (nullptr == pScene)
	{
		LogErrFmtPrint("[logic] SceneMgr::CreatureTransSceneSuccess, cannt find dest scence, id:%u , dstscene:%u, dstmap:%u ,cid:%llu, kind:%d ", id, dstSceneId, dstMapId, creature_cid, creature_kind);
		return false;
	}
	//发送切换场景成功事件，通知其他模块处理
	string strTrans = trans_param.SerializeAsString();
	g_GetEvent()->FireExecute(EVENT_TRANS_SUCCESS, creature_cid, creature_kind, (void*)strTrans.c_str(), strTrans.length());

	return true;
}
//生物切换场景结果
bool SceneMgr::CreatureTransSceneResult(const char *data, uint32_t len)
{
	uint32_t id = g_GetLogicService()->GetID();
	CenterCreatureTransSceneResultRsp resultRsp;
	if (!resultRsp.ParseFromArray(data,len))
	{
		LogErrFmtPrint("[logic] SceneMgr::CreatureTransSceneResult....CenterCreatureTransSceneResultRsp parse failed...id:%u ",id);
		return false;
	}
	int32_t ret = resultRsp.result();
	uint32_t dstSceneId = resultRsp.dst_sceneid();
	uint32_t srcSceneId = resultRsp.cur_sceneid();
	int32_t creature_kind = resultRsp.creature_kind();
	CharIDType creature_cid = resultRsp.creature_cid();

	LogDebugFmtPrint("[logic] SceneMgr::CreatureTransSceneResult...id:%u ,ret:%d, dstscene:%u, srcScene:%u ,cid:%llu, kind:%d ", id,ret, dstSceneId, srcSceneId, creature_cid, creature_kind);
	//切场景结果，发送事件通知
	TransCheckResEvent resEvent;
	resEvent.result = ret;
	resEvent.creature_cid = creature_cid;
	resEvent.dst_sceneid = dstSceneId;
	g_GetEvent()->FireExecute(EVENT_TRANS_CHECK_RES, creature_cid, creature_kind, &resEvent, sizeof(resEvent));

	return true;

}

bool SceneMgr::IsClosed(uint32_t sceneId)
{
	DELMAP::iterator iter = m_delCacheMap.find(sceneId);
	if (iter != m_delCacheMap.end())
		return true;

	return false;
}

Creature* SceneMgr::GetCreature(CharIDType cid)
{
	Creature *pCreature = nullptr;
	mapScenes::iterator iterScene = m_Scenes.begin();
	for (; iterScene != m_Scenes.end(); ++iterScene)
	{
		Scene *pScene = iterScene->second;
		if (nullptr == pScene)
		{
			continue;
		}
		pCreature = pScene->GetCreature(cid);
		if (nullptr != pCreature)
		{
			break;
		}
	}
	return pCreature;
}

Creature* SceneMgr::GetCreature(uint32_t SceneId, CharIDType Cid)
{
	Scene *pScene = g_GetSceneMgr()->GetScene(SceneId);
	if (!pScene)
		return nullptr;
	return pScene->GetCreature(Cid);
}

Player *SceneMgr::GetPlayer(CharIDType cid)
{
	Player *pPlayer = nullptr;
	mapScenes::iterator iterScene = m_Scenes.begin();
	for (; iterScene != m_Scenes.end(); ++iterScene)
	{
		Scene *pScene = iterScene->second;
		if (nullptr == pScene)
		{
			continue;
		}
		pPlayer = pScene->GetPlayer(cid);
		if (nullptr != pPlayer)
		{
			break;
		}
	}
	return pPlayer;
}

Player *SceneMgr::GetPlayer(uint32_t sceneId, CharIDType cid)
{
	Scene *pScene = GetScene(sceneId);
	return (nullptr != pScene) ? pScene->GetPlayer(cid) : nullptr;
}

int32_t SceneMgr::GetPlayerCount()
{
	int32_t count = 0;
	mapScenes::iterator iterScene = m_Scenes.begin();
	for (; iterScene != m_Scenes.end(); ++iterScene)
	{
		Scene *pScene = iterScene->second;
		if (nullptr != pScene)
		{
			count += pScene->GetPlayerCount();
		}
	}
	return count;
}



Monster *SceneMgr::GetMonster(CharIDType cid)
{
	Monster *pMonster = nullptr;
	mapScenes::iterator iterScene = m_Scenes.begin();
	for (; iterScene != m_Scenes.end(); ++iterScene)
	{
		Scene *pScene = iterScene->second;
		if (nullptr == pScene)
		{
			continue;
		}
		pMonster = pScene->GetMonster(cid);
		if (nullptr != pMonster)
		{
			break;
		}
	}
	return pMonster;
}

Monster *SceneMgr::GetMonster(uint32_t sceneId, CharIDType cid)
{
	Scene *pScene = GetScene(sceneId);
	return (nullptr != pScene) ? pScene->GetMonster(cid) : nullptr;
}

Npc *SceneMgr::GetNpc(CharIDType cid)
{
	Npc *pNpc = nullptr;
	mapScenes::iterator iterScene = m_Scenes.begin();
	for (; iterScene != m_Scenes.end(); ++iterScene)
	{
		Scene *pScene = iterScene->second;
		if (nullptr == pScene)
		{
			continue;
		}
		pNpc = pScene->GetNpc(cid);
		if (nullptr != pNpc)
		{
			break;
		}
	}
	return pNpc;
}

Npc *SceneMgr::GetNpc(uint32_t sceneId, CharIDType cid)
{
	Scene *pScene = GetScene(sceneId);
	return (nullptr != pScene) ? pScene->GetNpc(cid) : nullptr;
}

Drop *SceneMgr::GetDrop(CharIDType cid)
{
	Drop *pDrop = nullptr;
	mapScenes::iterator iterScene = m_Scenes.begin();
	for (; iterScene != m_Scenes.end(); ++iterScene)
	{
		Scene *pScene = iterScene->second;
		if (nullptr == pScene)
		{
			continue;
		}
		pDrop = pScene->GetDrop(cid);
		if (nullptr != pDrop)
		{
			break;
		}
	}
	return pDrop;
}

Drop *SceneMgr::GetDrop(uint32_t sceneId, CharIDType cid)
{
	Scene *pScene = GetScene(sceneId);
	return (nullptr != pScene) ? pScene->GetDrop(cid) : nullptr;
}

CRebot *SceneMgr::GetRebot(CharIDType cid)
{
	CRebot *pRebot = nullptr;
	mapScenes::iterator iterScene = m_Scenes.begin();
	for (; iterScene != m_Scenes.end(); ++iterScene)
	{
		Scene *pScene = iterScene->second;
		if (nullptr == pScene)
		{
			continue;
		}
		pRebot = pScene->GetRebot(cid);
		if (nullptr != pRebot)
		{
			break;
		}
	}
	return pRebot;
}

CRebot *SceneMgr::GetRebot(uint32_t sceneId, CharIDType cid)
{
	Scene *pScene = GetScene(sceneId);
	return (nullptr != pScene) ? pScene->GetRebot(cid) : nullptr;
}

